package elijah.base.elijahbasedemo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.Nullable;

import io.reactivex.disposables.CompositeDisposable;

public class WaveProgressView extends View {
    private Paint paint;
    private int radius;
    private int width, height;
    float waveHeight = 10;
    public static final float WAVE_HEIGHT = 16;
    private ValueAnimator valueAnimator;
    private RectF rectF;
    private float rate = 0.5f;

    private int startColor = 0xff00ff96;
    private int endColor = 0xff108d62;
    private SurfaceHolder holder;
    private final CompositeDisposable renderDisposable = new CompositeDisposable();


    public void setColor(int[] colors) {

        startColor = colors[0];
        endColor = colors[1];
    }


    public WaveProgressView(Context context) {
        this(context, null);
    }

    public WaveProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WaveProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

        setFocusable(true);
        setFocusableInTouchMode(true);
        setKeepScreenOn(true);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    public WaveProgressView setRate(float rate) {
        if (rate == this.rate) {
            return this;
        }
        this.rate = Math.min(Math.max(rate, 0), 1);
        return this;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        valueAnimator = ValueAnimator.ofFloat(1f, 0f, -1f).setDuration(1000);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(animation -> {
            waveHeight = (float) ((float) animation.getAnimatedValue() * WAVE_HEIGHT * Math.sin(Math.PI * rate));
            postInvalidate();

        });
        valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
        valueAnimator.setRepeatCount(-1);


        valueAnimator.start();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        valueAnimator.cancel();

    }

    RadialGradient radialGradient;
    RadialGradient radialGradient2;
    LinearGradient linearGradient;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawWave(canvas);
    }

    public void drawWave(Canvas canvas) {
        canvas.translate(width / 2f, height / 2f);

        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(12);
        paint.setShader(radialGradient);
        canvas.drawCircle(0, 0, radius / 2f - 12, paint);

        paint.setShader(null);
        paint.setStrokeWidth(4);
        paint.setColor(0x4420ffdd);
        canvas.drawCircle(0, 0, radius / 2f - 16, paint);

        paint.setShader(null);
        paint.setShader(radialGradient2);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(0, 0, radius / 2f - 24, paint);

        paint.setShader(null);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL);

        float r = radius / 2f - 26;
        double startAngle = Math.acos(1 - rate * 2) / Math.PI * 180;
        float startSweep = (float) (90 - startAngle);
        float sweepAngle = (float) (startAngle * 2);
        float y = (r - 2 * r * rate);
        float x = (float) (Math.sqrt(r * r - y * y));

        paint.setAlpha(120);
        drawWave(canvas, path, -waveHeight, startSweep, sweepAngle, -x, x, y, linearGradient, paint);
        paint.setAlpha(255);
        drawWave(canvas, path, waveHeight, startSweep, sweepAngle, -x, x, y, linearGradient, paint);


    }

    public void drawWave(Canvas canvas, Path path, float waveHeight, float startSweep, float sweepAngle, float startX, float endX, float startY, LinearGradient linearGradient, Paint paint) {
        path.addArc(rectF, startSweep, sweepAngle);
        path.moveTo(startX, startY);
        float per = (endX - startX) / 2f;
        float offset = per / 2f;
        path.quadTo(startX + offset, startY - waveHeight, startX + per, startY);
        path.quadTo(startX + per + offset, startY + waveHeight, startX + 2 * per, startY);
        path.close();
        paint.setShader(linearGradient);
        canvas.drawPath(path, paint);
        path.reset();

    }

    Path path = new Path();

    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        radius = Math.min(w, h);

        linearGradient = new LinearGradient(width, height, width, 0, new int[]{endColor, startColor}, null, Shader.TileMode.CLAMP);
        radialGradient = new RadialGradient(0, 0, radius / 2f - 12, new int[]{0xff20ffdd, 0x2220ffdd}, null, Shader.TileMode.CLAMP);
        radialGradient2 = new RadialGradient(0, 0, radius / 2f - 24, new int[]{0x33ffffff, 0xffffffff}, new float[]{0.75f, 1f}, Shader.TileMode.CLAMP);
        rectF = new RectF(-radius / 2f + 26, -radius / 2f + 26, radius / 2f - 26, radius / 2f - 26);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        radius = Math.min(width, height);

    }


}
